package dao

import (
	"bufio"
	"os"
	"path/filepath"
	"strconv"
	"strings"
	"sync"
	"time"

	"github.com/gogf/gf/frame/g"
	"github.com/gogf/gf/os/glog"
)

const (
	DelayPushErr uint8 = 1 // 保存延迟推送内容的文件
	LineEndFlag        = "<<<==="
)

var (
	LineBreak = GetLineBreakForPlatform() // 平台换行符
)

type inToer interface {
	inTo(projectName, appName, msg string)
}

type DelayPush struct {
	delay bool // 延迟推送
	rwMu  sync.RWMutex
}

func (d *DelayPush) setDelay(b bool) (old bool) {
	d.rwMu.Lock()
	defer d.rwMu.Unlock()
	old = d.delay
	d.delay = b
	return old
}

func (d *DelayPush) getDelay() bool {
	d.rwMu.RLock()
	defer d.rwMu.RUnlock()
	return d.delay
}

// GetFileDirPath 获取file目录路径
func (d *DelayPush) GetFileDirPath() string {
	return filepath.Join(GetProjectDir("sentryservice"), "file")
}

// GetDelayFileName 根据类型返回存放延迟推送的内容
func (d *DelayPush) GetDelayFileName(typeNum uint8) (fileName string) {
	fileDir := d.GetFileDirPath()
	switch typeNum {
	case DelayPushErr:
		fileName = filepath.Join(fileDir, "delaypusherr.txt")
	}
	glog.Infof("GetDelayFileName typeNum: %d fileName: %s", typeNum, fileName)
	return
}

// GetSaveDelayChunk 获取保存延迟的块内容
func (d *DelayPush) GetSaveDelayChunk(projectName, appName, content string) string {
	// 保存协议如下:
	// 项目名 应用名
	// 内容
	// 结束分割符
	res := LineEndFlag + LineBreak
	res += projectName + " " + appName + LineEndFlag + LineBreak
	res += content + LineEndFlag + LineBreak
	res += ContentSpilt + LineBreak
	return res
}

// ParseDelayChunk 解析延迟
func (d *DelayPush) ParseDelayChunk(input string) (projectName, appName, content string) {
	// glog.Info("input: ", input)
	chunk := strings.Split(input, LineEndFlag)
	if len(chunk) <= 3 {
		return
	}

	// 保存协议如下:
	// 项目名 应用名
	// 内容
	// 结束分割符
	first := strings.Split(chunk[0], " ")
	projectName, appName = strings.Trim(first[0], LineBreak), strings.Trim(first[1], LineBreak)
	content = strings.Trim(chunk[1], LineBreak)
	return
}

// StartPushFile 开始推送
func (d *DelayPush) StartPushFile(f *os.File, in inToer) string {
	rows := bufio.NewScanner(f)
	buf := new(strings.Builder)
	returnBuf := new(strings.Builder) // 保存不满足推送时间的内容
	for rows.Scan() {
		rowStr := rows.Text()
		// fmt.Printf("rowStr: %q\n", rowStr)
		if rowStr == "" {
			continue
		}

		buf.WriteString(rowStr)
		if rowStr == ContentSpilt { // 开始处理
			projectName, appName, content := d.ParseDelayChunk(buf.String())
			// glog.Infof("projectName: %s, appName: %s, content: %s", projectName, appName, content)
			content = "【延时推送】" + LineBreak + content + LineBreak
			in.inTo(projectName, appName, content)
			buf.Reset()
			continue
		}
		buf.WriteString(LineBreak)
	}
	return returnBuf.String()
}

// NeedDelay 判断是否需要延迟推送
func (d *DelayPush) NeedDelay() bool {
	pushDur := g.Cfg().GetString("pusherrlog.push_dur")
	if dur := strings.Split(pushDur, "-"); len(dur) == 2 { // 延迟推送预处理
		s, e := dur[0], dur[1]
		startHour, _ := strconv.Atoi(s)
		endHour, _ := strconv.Atoi(e)
		curTimeObj := time.Now()
		curHour := curTimeObj.Hour()
		// glog.Infof("curHour: %d, startHour: %d, endHour: %d", curHour, startHour, endHour)
		return curHour < startHour || curHour > endHour
	}
	return false
}
